//
// Copyright (c) 2005 BroadVision, Inc. All rights reserved.
//
// This software is copyrighted.  Under the copyright laws, this software
// may not be copied, in whole or in part, without prior written consent
// of BroadVision, Inc. or its assignees.  This software is provided under
// the terms of a license between BroadVision and the recipient, and its
// use is subject to the terms of that license.
//
// This software may be protected by one or more U.S. and International
// patents.  Certain applications of BroadVision One-To-One software are
// covered by U.S. patent 5,710,887.
//
// TRADEMARKS: BroadVision and BroadVision One-To-One are registered
// trademarks of BroadVision, Inc., in the United States and the European
// Community, and are trademarks of BroadVision, Inc., in other
// countries.  The BroadVision logo, is a trademark of BroadVision, Inc.,
// in the United States and other countries. Additionally, IONA and Orbix
// are trademarks of IONA Technologies, Ltd.  RSA, MD5, and RC2 are
// trademarks of RSA Data Security, Inc.
//

package com.broadvision.manage.common.tools.action.user;

import java.util.*;
import java.security.Principal;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.Globals;

import com.broadvision.manage.tools.action.BaseAction;
import com.broadvision.portal.services.UserTemplate;
import com.broadvision.portal.services.util.TransferBeanUtils;
import com.broadvision.license2.*;
import com.broadvision.web.util.ViewDynaBean;
import com.broadvision.manage.common.tools.user.UserProfile;
import com.broadvision.manage.common.tools.user.UserSearch;
import com.broadvision.web.servlet.SessionVisitor;
import com.broadvision.system.accesscontrol.client.*;
import com.broadvision.visitor.client.VisitorManager;
import com.broadvision.visitor.client.Visitor;
import com.broadvision.portal.services.PortalVisitor;
import com.broadvision.data.common.DataConstants;
import com.broadvision.data.common.TableData;

/**
 * Searches users based on criteria
 */
public class UserSearchAction extends BaseAction {

  public static final String VIEW_BEAN_NAME = "mtUserSearchView";
  public static final String DTO_BEAN_NAME  = "mtUserSearchDTO";
  public static final String DTO_GROUP_BEAN_NAME  = "mtUserSearchGroupDTO";

  public static VisitorManager visitorManager = new VisitorManager();

  /**
   * Implements the action for searching users based on criteria.
   * <p> <p>
   * @param mapping <code>ActionMapping</code> object used to select this instance
   * @param form Optional <code>ActionForm</code> bean for this request (if any)
   * @param request <code>HttpServletRequest</code> object to process
   * @param response <code>HttpServletResponse</code> object to process
   * <p> <p>
   * @return <code>ActionForward</code> instance describing where and how
   * control should be forwarded, or null if the response has already been completed
   * <p> <p>
   * @throws Exception if an error occurs
   */
  public ActionForward processExecute(ActionMapping mapping,
				      ActionForm form,
				      HttpServletRequest request,
				      HttpServletResponse response)
     throws Exception
  {

    try {
      int serviceId = getServiceId(request);
      PortalVisitor agent = getPortalVisitor(request);
      Visitor visitor = agent.getVisitor();

      boolean canEdit = UserProfile.isPermitted(visitor, "Edit");
	  
	  // Validate the user to authorize for this operation
	  if (!canEdit && !UserProfile.isOrganizationAdmin(visitor)) {
		request.setAttribute(Globals.ERROR_KEY, "error.group.noGroupAdmin");
		return mapping.findForward("failure");
      }

      if ("userAssignRoles".equalsIgnoreCase(mapping.getParameter())) {
	UserUtils.setP(form, "assignRolesMessage", "userAssignRoles");
      }

      ViewDynaBean view = new ViewDynaBean(VIEW_BEAN_NAME, mapping);
      request.setAttribute(VIEW_BEAN_NAME, view);

      UserUtils.setP(view, "useFullName", new Boolean(!VisitorManager.isUsingFMLName()));
      String searchFor = mapping.getParameter();

      if (null != searchFor) {
	  UserUtils.setP(view, "searchFor", searchFor);
      }

      AccessManager accessMgr = AccessManager.instance();

      List orgAdmins = accessMgr.getOwnerObjectsForPrincipal((Principal)visitor, "OrganizationAdmin");
      
      List orgs = new ArrayList(0);
      UserUtils.setP(view, "organizationList", orgs);

      if (null != orgAdmins) {
        if (!isUserInRole(visitor, "UserAdmin")) {
	  for (Iterator it = orgAdmins.iterator(); it.hasNext(); ) {
	      ACObjectID ac = (ACObjectID) it.next();
	      ViewDynaBean oneDto = new ViewDynaBean(DTO_GROUP_BEAN_NAME, mapping);
	      UserUtils.setP(oneDto, "groupFQN", ac.getObjectID());
	      UserUtils.setP(oneDto, "name", extractPathName(ac.getObjectID()));
	      orgs.add(oneDto);
	  }
	}
      }
      
      String searchLetter = request.getParameter("searchLetter");
      boolean searchUsers = ((Boolean)UserUtils.getP(form, "searchUsers")).booleanValue();

      if (!searchUsers && 
	  (searchLetter == null || (searchLetter.trim().length() == 0))) {
	  UserUtils.setP(form, "userAlias", ""); 
	  UserUtils.setP(form, "firstName", "");
	  UserUtils.setP(form, "lastName", ""); 
	  return mapping.findForward("success");
      }

      UserSearch userSearch = new UserSearch();
      //
      // to make search service specific, call UserSearch.setServiceId
      // if not service specific, set serviceId to -1
      //
      boolean searchEntireSite = ((Boolean)UserUtils.getP(form, "searchEntireSite")).booleanValue();
      if(searchEntireSite){
        serviceId=-1;
      }
      userSearch.setServiceId(serviceId);
      TransferBeanUtils.copyPropertiesToModel(userSearch, form);
      
      userSearch.setUseFullName(!VisitorManager.isUsingFMLName());
      
      userSearch.setSearchLetter(request.getParameter("searchLetter"));
      
      // set the sorting from a key in the ApplicationResources file
      if (VisitorManager.isUsingFMLName()) {
	  
	  String firstName = "FIRST_NAME";
	  String middleName = "MIDDLE_NAME";
	  String lastName = "LAST_NAME";
	  
	  String sortOrder = getResources(request, "mt.messages").
	      getMessage(getLocale(request), 
			 "mt.user.userName.sortOrder",
			 firstName, 
			 middleName,
			 lastName);
	  if (0 == sortOrder.indexOf(firstName)) {
	      userSearch.setSortAttr(firstName);
	  }
	  else if (0 == sortOrder.indexOf(middleName)) {
	      userSearch.setSortAttr(middleName);
	  }
	  else {
	      userSearch.setSortAttr(lastName);
	  }
      }
      
      String groupFQN = (String) UserUtils.getP(form, "groupFQN");

      long[] matchingVisitorsNG = null;
      List   matchingVisitorsGroup = null;
      int    numOfVisitors = 0;
      boolean groupSearch = false;
      if (UserUtils.isEmptyString(groupFQN)) {
        // do regular search
        long[] unsortedMatchingVisitorsNG = userSearch.searchWithoutSortingFilter();
	numOfVisitors = unsortedMatchingVisitorsNG == null ? 0 : unsortedMatchingVisitorsNG.length;
        if (numOfVisitors > 0) {
          matchingVisitorsNG = new long[numOfVisitors];
          VisitorManager visitorManager = new VisitorManager();
          String[] propNames = new String[1];
          String userId = "USER_ID";
          propNames[0] = userSearch.getSortAttr();
          TableData tblData = visitorManager.getSortedValuesByIdList(unsortedMatchingVisitorsNG, propNames, true);
          for (int i = 0; i < numOfVisitors; i++) {
            matchingVisitorsNG[i] = tblData.getLongValue(i, userId);
          }
        }
      }
      else {
        groupSearch = true;
	matchingVisitorsGroup = userSearch.groupSearch();
	numOfVisitors = matchingVisitorsGroup == null ? 0 : matchingVisitorsGroup.size();
      }

      UserUtils.setP(view, "numOfUsers", new Integer(numOfVisitors));
      
      // pagination support
      
      int countOfResults = numOfVisitors;
      
      // entriesPerPage is always not null
      
      int entriesPerPage = ((Integer) UserUtils.getP(form, "entriesPerPage")).intValue();
      int firstEntry = 0;
      int lastEntry = countOfResults;
      int totalPageNumber = 1;
      int currentPageNumber = 1;
      
      if (countOfResults > entriesPerPage) {
	  
	  // currentPageNumber and totalPageNumber are always not null
	  currentPageNumber = ((Integer) UserUtils.getP(form, "currentPageNumber")).intValue();
	  
	  totalPageNumber = countOfResults / entriesPerPage;
	  if (countOfResults % entriesPerPage > 0) {
	      totalPageNumber++;
	  }
	  // if the entriesPerPage has been increased
	  if (currentPageNumber > totalPageNumber) {
	      currentPageNumber = totalPageNumber;
	  }
	  
	  if (currentPageNumber == 0) {
	      // first page
	      currentPageNumber = 1;
	  }
	  else {
	      firstEntry = (currentPageNumber - 1) * entriesPerPage;
	  }
	  lastEntry = firstEntry + entriesPerPage;
      }
      else {
	  entriesPerPage = countOfResults;
      }
      
      UserUtils.setP(form, "currentPageNumber", new Integer(currentPageNumber));
      UserUtils.setP(form, "totalPageNumber", new Integer(totalPageNumber));
      
      List dtos = new ArrayList(entriesPerPage);
      UserUtils.setP(view, "userList", dtos);
      
      for (int i = firstEntry; (i < countOfResults) && (i < lastEntry); i++) {
        long userId = (groupSearch) ? ((Long) matchingVisitorsGroup.get(i)).longValue() :  matchingVisitorsNG[i];
	Visitor v = null;
	try {
	  v = visitorManager.getVisitor(userId);
        } 
        catch (Exception eex) {
          // may be inactive
	  continue;
        }
	
	ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
	UserUtils.setP(oneDto, "userAlias", v.getUserAlias());   
	
	String formattedName = UserUtils.getFormattedName(v,
							  getResources(request, "mc.messages"), 
							  getLocale(request));
	
	UserUtils.setP(oneDto, "formattedName", formattedName);
	
	UserUtils.setP(oneDto, "city", v.getStringValue("CITY"));
	UserUtils.setP(oneDto, "state", v.getStringValue("STATE"));
	UserUtils.setP(oneDto, "phone", v.getStringValue("BUS_PHONE"));
	UserUtils.setP(oneDto, "email", v.getStringValue("EMAIL"));
	UserUtils.setP(oneDto, "userId", new Long(userId));	
	UserUtils.setP(oneDto, "canRemoveFromService", new Boolean(PortalVisitor.inService(serviceId, userId)));
	UserUtils.setP(oneDto, "canDelete", new Boolean(true));
	
	// these two users can't be deleted
	// one can't delete oneself as well
	if ("bvadmin".equals(v.getUserAlias()) ||
	    (userId == getVisitor(request).getId())) {
	    UserUtils.setP(oneDto, "canDelete", Boolean.FALSE);
	}
	
	Hashtable urlParams = new Hashtable();
	urlParams.put("userId", new Long(userId));
	
	UserUtils.setP(oneDto, "urlParams", urlParams);
	
	dtos.add(oneDto);
      } // end of for ... loop
      
      UserUtils.setP(view, "canEdit", new Boolean(UserProfile.isPermitted(visitor, "edit")));
      
    }
    catch(Exception ex) {
      ex.printStackTrace();
      request.setAttribute(Globals.ERROR_KEY, "error.application");
      return (mapping.findForward("failure"));
    }
    
    return mapping.findForward("success");
  }

  private String extractPathName(String fqn) {
      int i = fqn.indexOf(":");
      if (i < 0) {
	  return fqn;
      }
      else {
	  return fqn.substring(i + 1);
      }
  }

}

